/**
 * @license
 * Copyright 2021 Du Tian Wei
 * SPDX-License-Identifier: Apache-2.0
 */
// ++++ for OpenHarmony +++
// import util from '@ohos.util'
// let _TextDecoder = util.TextDecoder;
// ---- for OpenHarmony ---

// ++++ for nodejs +++
// import util from 'util'
// let _TextDecoder = util.TextDecoder;
// ---- for nodejs ---

let _TextDecoder = TextDecoder;
let _TextEncoder = TextEncoder;

let imgsuffixs = ['.png', '.jpg', '.jpeg'];
let soundsuffixs = ['.wav', '.mp3'];
let videosuffixs = ['.mp4'];
let textsuffixs = ['.txt'];
let fontsuffixs = ['.ttf', 'otf', 'woff', '.woff2'];
/**
 *   let url= arrayBufferToBase64(response);
 *   document.getElementById('img').src='data:image/jpeg;base64,'+url;
 * @param {ArrayBuffer} buffer 
 * @returns 
 */
function arrayBufferToBase64(buffer) {
    var binary = '';
    var bytes = new Uint8Array(buffer);
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i]);
    }
    return window.btoa(binary);
}
/**
 * 
 * @param {String} name 
 * @param {String[]} suffixs 
 * @returns 
 */

function endsWithIn(name, suffixs) {
    name = name.toLowerCase();
    for (let i = 0; i < suffixs.length; i++) {
        if (name.endsWith(suffixs[i])) {
            return true;
        }
    }
    return false;
}
/**
 * 
 * @param {String} name 必须小写
 * @returns 
 */
function mediaType(name) {
    /**
     * @type String
     */
    if (endsWithIn(name, soundsuffixs)) {
        return 'sound';
    }
    if (endsWithIn(name, imgsuffixs)) {
        return 'image';
    }
    if (endsWithIn(name, videosuffixs)) {
        return 'video';
    }
    if (endsWithIn(name, textsuffixs)) {
        return 'text';
    }
    console.warn('Unknown mediaType:' + name);
    return 'Unknown';
}
/**
 * 
 * @param {String} filename 必须小写
 * @returns 
 */
function fileType(filename) {
    let idx = filename.lastIndexOf('.');
    if (idx >= 0) {
        return filename.substring(idx);
    } else {
        return "";
    }
}
/**
 * 
 * @param {Uint8Array} u8Arr 
 */
function decodeU8ArrToStr(u8Arr) {
    let decoder = new _TextDecoder();
    return decoder.decode(u8Arr);
}
/**
 * 
 */
function encodeStrToU8Arr(str) {
    let encoder = new _TextEncoder();
    return encoder.encode(str);
}
function _atob(a) {
    return window.atob(a);
}
function int32toArrayBuffer(int32) {
    let ab = new ArrayBuffer(4);
    let dv = new DataView(ab);
    dv.setInt32(0, int32, false);
    return ab;
}
class BinaryBuffer {
    constructor(bufferOrSize = 32) {
        if (bufferOrSize instanceof ArrayBuffer) {
            // 如果传入的是 ArrayBuffer，使用现有的 ArrayBuffer
            this.buffer = new Uint8Array(bufferOrSize);
            this.capacity = this.buffer.length;
            this.writePos = this.capacity;
        } else if (bufferOrSize instanceof Uint8Array) {
            // 如果传入的是 Uint8Array，直接使用它
            this.buffer = bufferOrSize;
            this.capacity = this.buffer.length;
            this.writePos = this.capacity;
        } else {
            // 否则，初始化一个新的 Uint8Array
            this.capacity = bufferOrSize;
            this.buffer = new Uint8Array(this.capacity);
            this.writePos = 0;
        }

        this.view = new DataView(this.buffer.buffer, this.buffer.byteOffset, this.buffer.byteLength);
        this.readPos = 0;  // 当前读取位置
    }

    // 确保缓冲区有足够的空间
    ensureSize(size) {
        if (this.writePos + size > this.buffer.length) {
            let newBuffer = new Uint8Array((this.buffer.length + size) * 2);
            newBuffer.set(this.buffer);
            this.buffer = newBuffer;
            this.capacity = this.buffer.length;
            this.view = new DataView(this.buffer.buffer, this.buffer.byteOffset, this.buffer.byteLength);
        }
    }

    // 获取当前数据长度
    getDataLength() {
        return this.writePos;
    }

    // 获取缓冲区总长度
    getBufferLength() {
        return this.capacity;
    }
    // 写入 Int32 值
    writeInt32(value) {
        this.ensureSize(4);
        this.view.setInt32(this.writePos, value, true); // 小端字节序
        this.writePos += 4;
    }

    // 写入 Uint32 值
    writeUint32(value) {
        this.ensureSize(4);
        this.view.setUint32(this.writePos, value, true); // 小端字节序
        this.writePos += 4;
    }

    // 写入 Uint8 值
    writeUint8(value) {
        this.ensureSize(1);
        this.view.setUint8(this.writePos, value);
        this.writePos += 1;
    }

    // 写入 Uint32Array
    writeUint32Array(arr) {
        this.ensureSize(arr.length * 4);
        for (let i = 0; i < arr.length; i++) {
            this.writeUint32(arr[i]);
        }
    }

    // 写入 Uint8Array
    writeUint8Array(arr) {
        this.ensureSize(arr.length);
        this.buffer.set(arr, this.writePos);
        this.writePos += arr.length;
    }

    // 读取 Int32
    readInt32() {
        let value = this.view.getInt32(this.readPos, true); // 小端字节序
        this.readPos += 4;
        return value;
    }

    // 读取 Uint32
    readUint32() {
        let value = this.view.getUint32(this.readPos, true); // 小端字节序
        this.readPos += 4;
        return value;
    }

    // 读取 Uint8
    readUint8() {
        let value = this.view.getUint8(this.readPos);
        this.readPos += 1;
        return value;
    }
    readFloat32() {
        let v = this.view.getFloat32(this.readPos, true); // 小端字节序
        this.readPos += 4;
        return v;
    }

    // 读取 Uint32Array
    readUint32Array(length) {
        let arr = new Uint32Array(length);
        for (let i = 0; i < length; i++) {
            arr[i] = this.readUint32();
        }
        return arr;
    }

    // 读取 Uint8Array
    readUint8Array(length) {
        let arr = this.buffer.subarray(this.readPos, this.readPos + length);
        this.readPos += length;
        return arr;
    }

    // 按索引读取 Int32
    readInt32At(index) {
        return this.view.getInt32(index, true); // 小端字节序
    }

    // 按索引读取 Uint32
    readUint32At(index) {
        return this.view.getUint32(index, true); // 小端字节序
    }

    // 按索引读取 Uint8
    readUint8At(index) {
        return this.view.getUint8(index);
    }
    readFloat32At(index) {
        return this.view.getFloat32(index, true); // 小端字节序
    }

    // 按索引写入 Int32
    writeInt32At(index, value) {
        this.view.setInt32(index, value, true); // 小端字节序
    }
    writeFloat32At(index, value) {
        this.ensureSize(4);
        this.view.setFloat32(index, value, true); // 小端字节序
    }

    // 按索引写入 Uint32
    writeUint32At(index, value) {
        this.view.setUint32(index, value, true); // 小端字节序
    }

    // 按索引写入 Uint8
    writeUint8At(index, value) {
        this.view.setUint8(index, value);
    }
    writeFloat32(value) {
        this.ensureSize(4);
        this.view.setFloat32(this.writePos, value, true); // 小端字节序
        this.writePos += 4;
    }
}
function int8ArrayToNumberArray(int8Array) {
    const numberArray = [];
    for (let i = 0; i < int8Array.length; i++) {
        numberArray[i] = int8Array[i];
    }
    return numberArray;
}
function int8ArrayToNumberArrayAsInt32(int8Array) {
    // 确保长度是4的倍数
    if (int8Array.length % 4 !== 0) {
        throw new Error("Int8Array的长度必须是4的倍数");
    }

    const numberArray = [];

    for (let i = 0; i < int8Array.length; i += 4) {
        // 使用按位运算符将4个 Int8 合并为一个 32-bit 的 number
        const number = (int8Array[i] << 24) |
            ((int8Array[i + 1] & 0xFF) << 16) |
            ((int8Array[i + 2] & 0xFF) << 8) |
            (int8Array[i + 3] & 0xFF);

        numberArray.push(number);
    }

    return numberArray;
}
function int32ArrayToBlob(intArray, mime) {
    // 将整数数组转为 Uint8Array，适用于8位整数。可以根据需要选择其他类型化数组。
    const typedArray = Int32Array.from(intArray);

    // 使用 Blob 构造函数创建 Blob 对象
    const blob = new Blob([typedArray], { type: mime || 'application/octet-stream' });

    return blob;
}
function int8ArrayToBlob(intArray, mime) {
    // 将整数数组转为 Uint8Array，适用于8位整数。可以根据需要选择其他类型化数组。
    const typedArray = Int8Array.from(intArray);

    // 使用 Blob 构造函数创建 Blob 对象
    const blob = new Blob([typedArray], { type: mime || 'application/octet-stream' });

    return blob;
}
export {
    _TextDecoder as TextDecoder,
    _TextEncoder as TextEncoder,
    BinaryBuffer,
    arrayBufferToBase64,
    fileType,
    mediaType,
    endsWithIn as endsWith,
    decodeU8ArrToStr,
    encodeStrToU8Arr,
    int32toArrayBuffer,
    _atob as atob,
    int8ArrayToNumberArrayAsInt32,
    int32ArrayToBlob,
    int8ArrayToNumberArray,
    int8ArrayToBlob
};